#pragma once

namespace SD_Tools
{
	namespace MathHelper
	{
		template<typename T> T GetDiff(T a, T b);
		template<typename T> T GetMax(T a, T b);
		template<typename T> T GetMin(T a, T b);
		template<typename T> bool IsNear(T a, T b, T Range);
		template<typename T> T ToRange(T a, T Left, T Right);
		template<typename T> T FixRange(T a, T Left, T Right);
		template<typename T> T GetRange(T a, T b, T Left, T Right);
		template<typename T> T GetRangeSigned(T a, T b, T Left, T Right);
		template<typename T> bool IsInRange(T a, T b, T Left, T Right, T Range);
		double RadToDeg(double Alpha);
		double DegToRad(double Alpha);
		float RadToDegf(float Alpha);
		float DegToRadf(float Alpha);


		//************************************
		// Method:    GetDiff
		// Profit:	  Gets the Difference between a and b, the operators >, < and - should be implemented
		// FullName:  SD_Tools::MathHelper<T>::GetDiff
		// Returns:   T
		// Notes:
		// -"return ((a>b) ? (a-b) : (b-a));"
		//************************************
		template<typename T> T GetDiff( T a, T b )
		{
			return ((a>b) ? (a-b) : (b-a));
		}

		//************************************
		// Method:    GetMax
		// Profit:	  Gets the greater one
		// FullName:  SD_Tools::MathHelper<T>::GetMax
		// Returns:   T
		// Notes:
		// -"return (a>b) ? a : b;"
		//************************************
		template<typename T> T GetMax( T a, T b )
		{
			return (a>b) ? a : b;
		}

		//************************************
		// Method:    GetMin
		// Profit:	  Gets the smaller one
		// FullName:  SD_Tools::MathHelper<T>::GetMin
		// Returns:   T
		// Notes:
		// -"return (a>b) ? b : a;"
		//************************************
		template<typename T> T GetMin( T a, T b )
		{
			return (a>b) ? b : a;
		}

		//************************************
		// Method:    IsNear
		// Profit:	  returns true if a is in <Range> of b
		// FullName:  SD_Tools::MathHelper<T>::IsNear
		// Returns:   bool
		// Notes:
		// -"return (b-Range < a && b+Range > a);"
		//************************************
		template<typename T> bool IsNear( T a, T b, T Range )
		{
			return (b-Range < a && b+Range > a);
		}

		//************************************
		// Method:    ToRange
		// Profit:	  Converts a in the left - right interval
		// FullName:  SD_Tools::MathHelper<T>::ToRange
		// Returns:   T
		// Notes:
		// -None
		//************************************
		template<typename T> T ToRange( T a, T Left, T Right )
		{
			while ((a < Left) || (a > Right))
			{
				if (a < Left)
				{
					a += Right - Left;
				}
				else if (a > Right)
				{
					a -= Right - Left;
				}
			}
			return a;
		}

		//************************************
		// Method:    FixRange
		// Profit:	  Fixes a in the left - right interval
		// FullName:  SD_Tools::MathHelper<T>::FixRange
		// Returns:   T
		// Notes:
		// -None
		//************************************
		template<typename T> T FixRange( T a, T Left, T Right )
		{
			if (a < Left)
			{
				a = Left;
			}
			else if (a > Right)
			{
				a = Right;
			}
			return a;
		}

		//************************************
		// Method:    GetRange
		// Profit:	  returns the difference of a and b in a circle interval from left to right
		// FullName:  SD_Tools::MathHelper<T>::GetRange
		// Returns:   T
		// Notes:
		// -None
		//************************************
		template<typename T> T GetRange( T a, T b, T Left, T Right )
		{
			T Rslt;
			T TotalRange = Right-Left;
			if (a < b)
			{
				Rslt = a;
				a = b;
				b = Rslt;
			}
			Rslt = a - b;
			if (Rslt > TotalRange/2)
			{
				Rslt -= TotalRange;
			}
			if (Rslt < 0)
			{
				Rslt *= -1;
			}
			return Rslt;
		}

		//************************************
		// Method:    GetRangeSigned
		// Profit:	  returns the signed difference of a and b in a circle interval from left to right
		// FullName:  SD_Tools::MathHelper<T>::GetRangeSigned
		// Returns:   T
		// Notes:
		// -None
		//************************************
		template<typename T> T GetRangeSigned( T a, T b, T Left, T Right )
		{
			T Rslt;
			T TotalRange = Right-Left;
			if (a < b)
			{
				Rslt = a;
				a = b;
				b = Rslt;
			}
			Rslt = a - b;
			if (Rslt > TotalRange/2)
			{
				Rslt -= TotalRange;
			}
			return Rslt;
		}

		//************************************
		// Method:    IsInRange
		// Profit:	  Returns true if a is in the <Range> of b in the circle interval left-right
		// FullName:  SD_Tools::MathHelper<T>::IsInRange
		// Returns:   bool
		// Notes:
		// -None
		//************************************
		template<typename T> bool IsInRange( T a, T b, T Left, T Right, T Range )
		{
			T temp;
			temp = GetRange(a,b,Left,Right);
			if (temp <= range)
			{
				return true;
			}
			return false;
		}

		//************************************
		// Method:    RadToDeg
		// Profit:	  Converts a double Radian to Degree
		// FullName:  SD_Tools::MathHelper::RadToDeg
		// Returns:   double
		// Notes:
		// -None
		//************************************
		double RadToDeg(double Alpha)
		{
			return (Alpha*(180.0/SD_PI));
		}

		//************************************
		// Method:    DegToRad
		// Profit:	  Converts a double Degree to Radian
		// FullName:  SD_Tools::MathHelper::DegToRad
		// Returns:   double
		// Notes:
		// -None
		//************************************
		double DegToRad(double Alpha)
		{
			return  (Alpha/(180.0/SD_PI));
		}

		//************************************
		// Method:    RadToDegf
		// Profit:	  Converts a float Radian to Degree
		// FullName:  SD_Tools::MathHelper::RadToDegf
		// Returns:   float
		// Notes:
		// -None
		//************************************
		float RadToDegf(float Alpha)
		{
			return (Alpha*(180.0f/SD_PI_F));
		}

		//************************************
		// Method:    DegToRadf
		// Profit:	  Converts a float Degree to Radian
		// FullName:  SD_Tools::MathHelper::DegToRadf
		// Returns:   float
		// Notes:
		// -None
		//************************************
		float DegToRadf(float Alpha)
		{
			return (Alpha/(180.0f/SD_PI_F));
		}

	} // End of Namespace MathHelper
}